#include<iostream>
#include"calculator.h"
#include<cmath>

calculator::calculator(){
  result=0.0;//初始化
}

void calculator::get_postfix(){
  char c;//暂存输入字符
  std::string tmp;//暂存转换字符串
  bool digit=false;//处理数字
  bool point=false;//处理小数
  bool opright=false;//检查运算符逻辑
  while(true){
    c=std::getchar();//逐个字符输入并处理
    if(c=='\n'){
      if(digit){//处理最后一个长数字
	exp.push(tmp);
	digit=false;
	break;
      }
      else
	break;
    }
    if(c==' '||c=='\t')
      continue;
    if(c>='0' && c<='9'){
      if(digit)//处理长数字
	tmp+=c;
      else{
	tmp=c;
        digit=true;
      }
      opright=true;//数字后可以加运算符
    }
    else if(c=='.'){
      if(digit&&!point){//非数字不能加小数点，小数点不能重复加
	tmp+=c;
	point=true;
	opright=false;//小数点后不能加运算符或括号
      }
      else
	_err_exp(1);
    }
    else{
      if(digit){
	if(point&&!opright)//小数点后不能加运算符或括号
	  _err_exp(1);
	exp.push(tmp);
	digit=false;
	point=false;
      }
      if(c==')'){
	if(op.empty()||op.top()==')')//右括号必须与左括号匹配
	  _err_exp(2);
	if(!opright)//右括号前必须是数字
	  _err_exp(4);
	while(!op.empty()&&op.top()!='('){
	  tmp=op.top();
	  exp.push(tmp);
	  op.pop();
	}
	if(op.empty())//右括号必须与左括号匹配
	  _err_exp(2);
	else
	  op.pop();
      }
      else if(c=='+'||c=='-'){
	if(!opright){//运算符前必须是数字或者右括号
	  if(c=='-'&&(op.top()=='('||exp.empty())){//对负数进行处理
	    tmp='0';
	    exp.push(tmp);
	  }else
	    _err_exp(4);
	}
	else if(!op.empty()){
	  while(!op.empty()&&op.top()!='('){
	    tmp=op.top();
	    exp.push(tmp);
	    op.pop();
	  }
	}
	op.push(c);
	opright=false;
      }
      else if(c=='*'||c=='/'){
	if(!opright)//运算符前必须是数字或者右括号
	  _err_exp(4);
	if(!op.empty()){
	  while(!op.empty()&&op.top()!='('&&op.top()!='+'&&op.top()!='-'){
	    tmp=op.top();
	    exp.push(tmp);
	    op.pop();
	  }
	}
	op.push(c);
	opright=false;
      }
      else if(c=='^'){
	if(!opright)//运算符前必须是数字或者右括号
	  _err_exp(4);
	//乘方运算从右往左，相当与无同级与最高级
	op.push(c);
	opright=false;
      }
      else if(c=='('){
	if(opright)//左括号前必须是运算符或者左括号
	  _err_exp(4);
	op.push(c);
      }
      else
	_err_exp(3);
    }
  }
  while(!op.empty()){
    if(op.top()!='('&&op.top()!=')'){
      tmp=op.top();
      exp.push(tmp);
      op.pop();
    }else
      _err_exp(2);
  }
}

void calculator::_err_exp(int i)
{
  if(i==0)
    std::cerr<<"错误：除数为0"<<std::endl;
  else if(i==1)
    std::cerr<<"错误：小数输入不合逻辑"<<std::endl;
  else if(i==2)
    std::cerr<<"错误：括号不匹配"<<std::endl;
  else if(i==3)
    std::cerr<<"错误：表达式超过运算范围"<<std::endl;
  else if(i==4)
    std::cerr<<"错误：运算符不合逻辑"<<std::endl;
  else if(i==5)
    std::cerr<<"错误：乘方无意义"<<std::endl;
  std::exit(-1);
}


void calculator::calresult(){
  double num1=0,num2=0;//设置两个初始化运算对象
  std::string tmp;//调用后缀表达式
  std::stack<double> cal;//存放运算对象
  while(!exp.empty()){
    tmp = exp.front();
    if(tmp[0]>='0' && tmp[0]<='9'){
      num1=num2;
      num2=atof(tmp.c_str());//将string类型的运算对象转化为double类型计算
      cal.push(num2);
    }
    else if(tmp[0]=='+'||tmp[0]=='-'||tmp[0]=='*'||tmp[0]=='/'||tmp[0]=='^'){
      if(tmp[0]=='+')
	num2=num1+num2;
      else if(tmp[0]=='-')
	num2=num1-num2;
      else if(tmp[0]=='*')
	num2=num1*num2;
      else if(tmp[0]=='/'){
	if(num2==0)
	  _err_exp(0);
	else
	  num2=num1/num2;
      }
      else{
	if(num1==0&&num2<=0)
	  _err_exp(5);
	else
	  num2=std::pow(num1,num2);
      }
      cal.pop();
      cal.pop();
      if(!cal.empty())
	num1=cal.top();
      cal.push(num2);
    }
    exp.pop();
  }
  result=cal.top();
}

double calculator::get_result(){
  return result;
}

void calculator::calculate(){
  get_postfix();
  calresult();
}

